﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Timers;
using Reborn_Server.App1AppHandler;
using Reborn_WorldServer.App1AppHandler;

namespace App1AppHandler
{
    public class Creature : CreatureBase
    {
        public int Respawn_Min = -1;
        public int StartMapID = -1;
        public int StartMapX = -1;
        public int StartMapY = -1;
        public int StartLeftHand = -1;
        public int StartRightHand = -1;

        public int MaxMoves = 0;
        public int RunHPPercent = 0;

        public int Defense = 1;
        public int DefenseSkill = 1;
        public string HandBlockWeapon = "";

        public string SoundEnterCombat = "";

        public int WanderMax_W = -1;
        public int WanderMax_N = -1;
        public int WanderMax_E = -1;
        public int WanderMax_S = -1;

        public int CoinsLow = 0;
        public int CoinsHigh = 0;

        public bool RushAttack = false;
        public bool RangeAttack = false;

        public bool IgnoresFire = false;
        public bool IgnoresIce = false;
        public bool IgnoresHoly = false;
        public bool IgnoresUnholy = false;
        public bool IgnoresMagic = false;
        public bool Smart = false;

        public int WaterMotion = -1;

        public double BaseMovementSpeed = 3;

        public int BaseArmor = 0;

        public int BaseResistFire = 0;
        public int BaseResistIce = 0;
        public int BaseResistHoly = 0;
        public int BaseResistUnholy = 0;
        public int BaseResistMagic = 0;
        public int BaseResistPhysical = 0;

        //List of items to put on corpse when creature dies
        public List<Loot> LootItems = new List<Loot>();

        //From DB, used to generage loot drops when creature gets reset
        public List<LootDrop> LootDrops = new List<LootDrop>();
        
        //Controls creatures actions
        public CreatureAI creatureAI;

        public AttackSequenceManager attackSequenceManager;

        public override void copyFrom(CreatureBase copyFromCreature)
        {
            base.copyFrom(copyFromCreature);

            if (!(copyFromCreature is Creature))
                return;

            Creature copyFromCrit = (Creature)copyFromCreature;

            //this.CreatureID = Managers.GameHandler.ItemIDGen.GetCreatureUID();

            this.WaterMotion = copyFromCrit.WaterMotion;

            this.StartMapX = copyFromCrit.StartMapX;
            this.StartMapY = copyFromCrit.StartMapY;
            this.StartMapID = copyFromCrit.StartMapID;

            this.StartLeftHand = copyFromCrit.StartLeftHand;
            this.StartRightHand = copyFromCrit.StartRightHand;

            this.MaxMoves = copyFromCrit.MaxMoves;
            this.Respawn_Min = copyFromCrit.Respawn_Min;

            this.WanderMax_N = copyFromCrit.WanderMax_N;
            this.WanderMax_E = copyFromCrit.WanderMax_E;
            this.WanderMax_S = copyFromCrit.WanderMax_S;
            this.WanderMax_W = copyFromCrit.WanderMax_W;

            this.CoinsLow = copyFromCrit.CoinsLow;
            this.CoinsHigh = copyFromCrit.CoinsHigh;

            this.buffManager.HasInnateNightVision = copyFromCreature.buffManager.HasInnateNightVision;

            this.RushAttack = copyFromCrit.RushAttack;
            this.RangeAttack = copyFromCrit.RangeAttack;
            this.Defense = copyFromCrit.Defense;
            this.DefenseSkill = copyFromCrit.DefenseSkill;
            this.HandBlockWeapon = copyFromCrit.HandBlockWeapon;
            this.SoundEnterCombat = copyFromCrit.SoundEnterCombat;
            this.RunHPPercent = copyFromCrit.RunHPPercent;

            this.Armor = copyFromCrit.Armor;

            this.BaseMovementSpeed = copyFromCrit.BaseMovementSpeed;
            this.MovementSpeed = copyFromCrit.BaseMovementSpeed;

            this.BaseResistFire = copyFromCrit.BaseResistFire;
            this.ResistFire = copyFromCrit.BaseResistFire;

            this.BaseResistIce = copyFromCrit.BaseResistIce;
            this.ResistIce = copyFromCrit.BaseResistIce;

            this.BaseResistHoly = copyFromCrit.BaseResistHoly;
            this.ResistHoly = copyFromCrit.BaseResistHoly;

            this.BaseResistUnholy = copyFromCrit.BaseResistUnholy;
            this.ResistUnholy = copyFromCrit.BaseResistUnholy;

            this.BaseResistMagic = copyFromCrit.BaseResistMagic;
            this.ResistMagic = copyFromCrit.BaseResistMagic;

            this.BaseResistPhysical = copyFromCrit.BaseResistPhysical;
            this.ResistPhysical = copyFromCrit.BaseResistPhysical;

            this.BaseArmor = copyFromCrit.BaseArmor;
            this.Armor = copyFromCrit.BaseArmor;

            this.IgnoresFire = copyFromCrit.IgnoresFire;
            this.IgnoresIce = copyFromCrit.IgnoresIce;
            this.IgnoresHoly = copyFromCrit.IgnoresHoly;
            this.IgnoresUnholy = copyFromCrit.IgnoresUnholy;
            this.IgnoresMagic = copyFromCrit.IgnoresMagic;

            this.Smart = copyFromCrit.Smart;
            setXmlData(copyFromCrit.xmlData);

            //Shallow copy, these should never change, we dont need to deep copy.
            this.LootDrops = copyFromCrit.LootDrops;
            this.attackSequenceManager.Attacks = copyFromCrit.attackSequenceManager.Attacks;
            this.attackSequenceManager.Spells = copyFromCrit.attackSequenceManager.Spells;
            this.stackTypeImmunities = copyFromCrit.stackTypeImmunities;
        }


        private List<Pet_Controller> pets = new List<Pet_Controller>();
        public void addPet(Pet_Controller pet)
        {
            lock (pets)
            {
                pets.Add(pet);
            }
        }
        public void removePet(Pet_Controller pet)
        {
            lock (pets)
            {
                pets.Remove(pet);
            }
        }
        private void dismissAllPets()
        {
            List<Action> dismissMethods = new List<Action>();
            lock (pets)
            {
                foreach (Pet_Controller pc in pets)
                {
                    Action dismissMethod = pc.Dismiss;
                    dismissMethods.Add(dismissMethod);
                }
            }
            //Async this because the dismiss could lock a 2nd map resulting in a deadlock.
            foreach (Action a in dismissMethods)
                a.BeginInvoke(null, null);
        }

        private string _xmlData;
        public string xmlData
        {
            get { return _xmlData; }
        }
        virtual public void setXmlData(string xmlData)
        {
            _xmlData = xmlData;
        }

        public List<string> stackTypeImmunities = new List<string>();
        public bool isImmune(SpellIcon spellIcon)
        {
            foreach (string stackType in stackTypeImmunities)
            {
                if (stackType == spellIcon.StackType)
                    return true;
            }
            return false;
        }
        public bool isImmune(string stackType)
        {
            foreach (string st in stackTypeImmunities)
            {
                if (st.ToLower() == stackType.ToLower())
                    return true;
            }
            return false;
        }

        virtual public void runAI()
        {
            creatureAI.runAI();
        }

        //Constructor
        public Creature(AppHandler2 gameHandler) : base(gameHandler)
        {
            Creature thisCreature = this;
            creatureAI = new CreatureAI(thisCreature);
            attackSequenceManager = new AttackSequenceManager(thisCreature);
        }

        public override int HP
        {
            get
            {
                return base.HP;
            }
            set
            {
                if (CreatureType == "Binder" || CreatureType == "AlchemyTrainer")
                    value = MaxHP;

                base.HP = value;

                if (base.HP < 1)
                {
                    dismissAllPets();
                }
            }
        }

        public override void SetPosition(MapItem mapItem)
        {
            base.SetPosition(mapItem);

            Timer_HexDamage_Stop();

            if (mapItem.TerrainType == "Water" || mapItem.TerrainType == "Door" || mapItem.TerrainType == "SDoor")
            {
                if (petController != null)
                {
                    if (mapItem.ColorUrl.IndexOf("Lava2") > -1)
                        Timer_HexDamage_Start("Lava2");
                    else if (mapItem.ColorUrl.IndexOf("Lava") > -1)
                        Timer_HexDamage_Start("Lava");
                    else
                        Timer_HexDamage_Start("Water");
                }
            }
        }
        override protected void Timer_HexDamage_Elapsed(object source, ElapsedEventArgs e)
        {
            LockItem myLockItem = GameHandler.GetLockItem(MapID, Instance);
            lock (myLockItem.LockObj)
            {
                //CHECK IF WE'RE IN A VALID STATE TO CONTINUE EXECUTION/////////////////////////

                //System.Reflection.MethodBase currentMethodBase = System.Reflection.MethodBase.GetCurrentMethod();
                //Delegate currentMethodDelegate = Delegate.CreateDelegate(currentMethodBase.GetType(), this, currentMethodBase.Name);

                //Create a delegate for this method incase it cant be run right now
                Action<object, ElapsedEventArgs> thisMethod = (Action<object, ElapsedEventArgs>)Timer_HexDamage_Elapsed;
                //Record this method's arguments
                Object[] thisMethodArgs = { source, e };
                //Pass the delegate and args when we check if we're mid map transfer. If yes, they will be recorded and run again automatically.
                if (isChangingMaps(thisMethod, thisMethodArgs) == true)
                    return;

                //A map transfer happened, but its already complete. Immediately re-run this method on a different thread. 
                //We need to use a different thread because otherwise the current thread would lock 2 maps possibly resulting in a deadlock.
                if (MapID != myLockItem.MapID)
                {
                    thisMethod.BeginInvoke(MapID, e, null, null);
                    return;
                }
                //STATE IS VALID, CONTINUE EXECUTION///////////////////////////////////////////

                //Timer has been shut off, do nothing
                if (Timer_HexDamageCounter == -1)
                    return;

                //Increments the counter
                base.Timer_HexDamage_Elapsed(source, e);

                //Do nothing if this creature is dead
                if (this.HP < 1)
                    return;

                if (Timer_HexDamageType == "Lava2")
                {
                    if (buffManager.HasBreatheWater() == true)
                        Timer_HexDamageCounter = 0;

                    //Damage Character for drowning
                    int lavaFireDamage = 450;
                    lavaFireDamage = CalculateGetSpellDamagePerResists(lavaFireDamage, "Fire");

                    List<Character> CharsToUpdate = new List<Character>();

                    foreach (MapItem mapitem in currentMapItem.mapItemsWithin8)
                    {
                        foreach (CreatureBase creaturebase in mapitem.CreaturesBases)
                        {
                            if (creaturebase is Character)
                                CharsToUpdate.Add((Character)creaturebase);
                        }
                    }
                    InflictDamage(lavaFireDamage, -1);
                    if (this.HP < 1)
                        currentMapItem.CreaturesBases.Remove(this);

                    foreach (Character character in CharsToUpdate)
                    {
                        if (this.HP < 1)
                        {
                            character.AddMapItem(currentMapItem);
                            character.PlaySound(this.SoundDeath, this.MapX, this.MapY);
                        }
                        else
                            character.UpdateCreatureBaseHp(this);
                    }
                }
                else if (Timer_HexDamageType == "Lava")
                {
                    if (buffManager.HasBreatheWater() == true)
                        Timer_HexDamageCounter = 0;

                    //Damage Character for drowning
                    int lavaFireDamage = 250;
                    lavaFireDamage = CalculateGetSpellDamagePerResists(lavaFireDamage, "Fire");

                    List<Character> CharsToUpdate = new List<Character>();

                    foreach (MapItem mapitem in currentMapItem.mapItemsWithin8)
                    {
                        foreach (CreatureBase creaturebase in mapitem.CreaturesBases)
                        {
                            if (creaturebase is Character)
                                CharsToUpdate.Add((Character)creaturebase);
                        }
                    }
                    InflictDamage(lavaFireDamage, -1);
                    
                    if (this.HP < 1)
                        currentMapItem.CreaturesBases.Remove(this);

                    foreach (Character character in CharsToUpdate)
                    {
                        if (this.HP < 1)
                        {
                            character.AddMapItem(currentMapItem);
                            character.PlaySound(this.SoundDeath, this.MapX, this.MapY);
                        }
                        else
                            character.UpdateCreatureBaseHp(this);
                    }
                }
            }//End Lock

            Timer_HexDamage.Start();
        }


        //Resets Creature Stats, Position, Generates Loot
        public virtual void ResetCreature()
        {
            //RESET HP & POSITION
            this.HP = this.MaxHP;
            this.Stamina = this.MaxStamina;
            this.Mana = this.MaxMana;

            this.MapID = this.StartMapID;

            //CREATE HAND ITEMS
            if (this.StartRightHand != -1)
                this.RightHand = GameHandler.CreateItem(this.StartRightHand);
            else
                this.RightHand = null;

            if (this.StartLeftHand != -1)
                this.LeftHand = GameHandler.CreateItem(this.StartLeftHand);
            else
                this.LeftHand = null;

            LootItems = new List<Loot>();
            List<LootDrop> UniqueLoot = new List<LootDrop>();
            foreach (LootDrop lootDrop in LootDrops)
            {
                int Rate;
                if (lootDrop.IsUnique == false)
                {
                    Rate = GameHandler.random.Next(1, 10000);
                    if (Rate <= lootDrop.LootDropRate)
                    {
                        LootItems.Add(GameHandler.CreateItem(lootDrop.LootID));
                    }
                }
                else
                {
                    UniqueLoot.Add(lootDrop);
                }
            }
            if (UniqueLoot.Count > 0)
            {
                int range = 0;
                foreach (LootDrop lootDrop in UniqueLoot)
                {
                    range = range + lootDrop.LootDropRate;
                }
                int rangeResult = GameHandler.random.Next(1, range + 1);

                int counter = 0;
                foreach (LootDrop lootDrop in UniqueLoot)
                {
                    counter = counter + lootDrop.LootDropRate;
                    if (counter >= rangeResult)
                    {
                        LootItems.Add(GameHandler.CreateItem(lootDrop.LootID));
                        break;
                    }
                }
            }

            this.attackSequenceManager.ResetSequence();
            this.Coins = GameHandler.random.Next(this.CoinsLow, this.CoinsHigh + 1);
        }
        
        //Creates Corpse, Drops Corpse and held items on ground
        public override void DropLoot(int SlayingCharID)
        {
            base.DropLoot(SlayingCharID);

            //Do nothing if this creature does not drop a corpse (such as a pet)
            if (CorpseImageURL == null || CorpseImageURL == "")
                return;

            Corpse MyCorpse = new Corpse(GameHandler);
            MyCorpse.GameUID = GameHandler.ItemIDGen.GetUID();
            MyCorpse.CanConsume = false;
            MyCorpse.Bag = false;
            MyCorpse.ClassName = "";
            MyCorpse.ID = -2;
            MyCorpse.ImageURL = this.CorpseImageURL;
            MyCorpse.ItemType = "Corpse";
            MyCorpse.Name = this.Name + "'s Corpse";

            foreach (Loot loot in LootItems)
            {
                //if loot bind type is binds on killing blow
                if (loot.BoundTo == -3)
                {
                    //Player killed this creature, bind the item to them
                    if (SlayingCharID != -1)
                        loot.BoundTo = SlayingCharID;
                    //A player did not kill this creature, so change the bind type to bind on pick up
                    else
                        loot.BoundTo = -2;
                }

                MyCorpse.LootToDrop.Add(loot);
            }

            if (this.Coins > 0)
            {
                Coins coins = new Coins(GameHandler);
                coins.NumCoins = this.Coins;
                coins.Bag = true;
                coins.CanConsume = false;
                coins.ID = -3;
                coins.GameUID = GameHandler.ItemIDGen.GetUID();
                coins.ImageURL = "Coin";
                coins.ItemType = "Coins";
                coins.Name = this.Coins.ToString() + " Coins";

                MyCorpse.LootToDrop.Add(coins);
            }

            List<Loot> ItemsToDrop = new List<Loot>();
            ItemsToDrop.Add(MyCorpse);

            if (this.LeftHand != null)
            {
                if (this.LeftHand.BoundTo == -3)
                {
                    //Player killed this creature, bind the item to them
                    if (SlayingCharID != -1)
                        this.LeftHand.BoundTo = SlayingCharID;
                    //A player did not kill this creature, so change the bind type to bind on pick up
                    else
                        this.LeftHand.BoundTo = -2;
                }
                ItemsToDrop.Add(this.LeftHand);
            }
            if (this.RightHand != null)
            {
                if (this.RightHand.BoundTo == -3)
                {
                    //Player killed this creature, bind the item to them
                    if (SlayingCharID != -1)
                        this.RightHand.BoundTo = SlayingCharID;
                    //A player did not kill this creature, so change the bind type to bind on pick up
                    else
                        this.RightHand.BoundTo = -2;
                }
                ItemsToDrop.Add(this.RightHand);
            }
            GameHandler.GetMap(MapID,Instance).LootMngr.DropItems(this.MapX, this.MapY, ItemsToDrop, false);
        }

        //Returns true if attack is successfull, false if blocked
        public bool AttackCreatureBase(List<Character> CharactersInUpdateRange, CreatureBase CreatureToAttack, List<MapItem> MapItemsInRange, bool UseRange, out int Delay)
        {
            CreatureAttackWeapon weapon = (CreatureAttackWeapon)attackSequenceManager.CurrentAction;
            attackSequenceManager.moveNextSequence();

            Pet_Controller pc = this.petController;
            if (!(this is QuestCreature) &&                                                     //Not a quest creature
                pc != null &&                                                                   //Is a pet
                CreatureToAttack is Character &&                                                //Attacking a character
                pc.MasterCreature.hateManager.GetCreatureHateInfo(CreatureToAttack) == null)    //Master does not have hate on prey
            {
                Character charToAttack = (Character)CreatureToAttack;
                if (charToAttack.friendsManager.hasNoSDFlag(pc.MasterCreature.ID) == false)
                {
                    if (CreatureToAttack.hateManager.GetCreatureHateInfo(pc.MasterCreature) == null)
                    {
                        CreatureToAttack.SendMessage("You have been ATTACKED by " + pc.MasterCreature.Name + "!", "damaged");
                        CreatureToAttack.PlaySound("Ding", CreatureToAttack.MapX, CreatureToAttack.MapY);

                        CreatureToAttack.hateManager.UpdateList(pc.MasterCreature, 0);

                        charToAttack.AddMapItem(pc.MasterCreature.currentMapItem);
                    }
                    else
                        CreatureToAttack.hateManager.UpdateList(pc.MasterCreature, 0);
                }
            }

            int dmg = GameHandler.random.Next(weapon.DmgLow, weapon.DmgHigh + 1);
            if (UseRange == true)
                dmg = SkillManager.AdjustForCombat(weapon.SkillLevel, dmg, DexterityTotal);
            else
                dmg = SkillManager.AdjustForCombat(weapon.SkillLevel, dmg, StrengthTotal);

            Delay = (int)(weapon.Speed * 1000);
            if (MeleeSpeedPercentModifier != 0 && UseRange == false)
            {
                decimal reduceBy = System.Convert.ToDecimal(Delay) * System.Convert.ToDecimal((MeleeSpeedPercentModifier / 100.00));
                Delay = Delay + System.Convert.ToInt32(Math.Floor(reduceBy));
            }
            else if (RangeSpeedPercentModifier != 0 && UseRange == true)
            {
                decimal reduceBy = System.Convert.ToDecimal(Delay) * System.Convert.ToDecimal((RangeSpeedPercentModifier / 100.00));
                Delay = Delay + System.Convert.ToInt32(Math.Floor(reduceBy));
            }

            int acc = SkillManager.AdjustForCombat(weapon.SkillLevel, weapon.Accuracy, DexterityTotal);

            //Used to change the multiplier on damage
            double damageMultiplier = 1;
            //Flag used to turn off the hit sound if we block but continue to let the method run and do damage.
            bool skipHitSound = false;

            //Check for miss
            int totalForMiss = 10 + acc;
            if (GameHandler.random.Next(1, totalForMiss + 1) < 11)
            {
                if (CreatureToAttack is Creature)
                    CreatureToAttack.hateManager.UpdateList(this, 0);

                foreach (Character character in CharactersInUpdateRange)
                {
                    if (UseRange == true)
                        character.PlaySound("ArrowMiss", MapX, MapY);
                    else
                        character.PlaySound("SwingMiss", MapX, MapY);
                }

                if (CreatureToAttack is Character)
                {
                    Character character = (Character)CreatureToAttack;

                    Message msg1 = new Message();
                    msg1.CreatureID = character.CreatureID;
                    msg1.Type = "damaged";
                    msg1.Text = this.Name + " misses you";

                    character.AddMessage(msg1);
                }

                return false;
            }

            bool parry;
            string BlockedByWeaponName = CreatureToAttack.DamageBlock(acc, this, out parry);

            if (BlockedByWeaponName == "Dodge")
            {
                foreach (Character character in CharactersInUpdateRange)
                {
                    if (UseRange == true)
                        character.PlaySound("ArrowMiss", MapX, MapY);
                    else
                        character.PlaySound("SwingMiss", MapX, MapY);
                }
                return false;
            }
            else if (BlockedByWeaponName != "")
            {
                foreach (Character character in CharactersInUpdateRange)
                {
                    if (UseRange == true)
                        character.PlaySound("ArrowBlockNonMetal", CreatureToAttack.MapX, CreatureToAttack.MapY);
                    else
                        character.PlaySound("SwingBlockNonMetal", CreatureToAttack.MapX, CreatureToAttack.MapY);
                }

                if (parry == true)
                {
                    Delay = Delay * 2;
                }

                Buff excessiveForceBuff = buffManager.GetBuff("Excessive Force");
                if (excessiveForceBuff != null)
                {
                    Spell_ExcessiveForce excessiveForce = (Spell_ExcessiveForce)excessiveForceBuff;
                    damageMultiplier = damageMultiplier * excessiveForce.GetMultiplier();
                    skipHitSound = true;
                }
                else
                    return false;
            }
            
            int damageAbsorbed;
            int actualDamage = CreatureToAttack.InflictDamageArmorReduce(dmg, this, out damageAbsorbed, UseRange, damageMultiplier, 0);

            if (CreatureToAttack is Character)
            {
                Character charToAttack = (Character)CreatureToAttack;

                Message msg = new Message();
                msg.CreatureID = charToAttack.CreatureID;
                msg.Type = "damaged";

                if (damageAbsorbed > 0)
                    msg.Text = this.Name + " " + weapon.Description.Replace("{name}","you") + "! (" + actualDamage.ToString() + ") ABSORBED " + damageAbsorbed.ToString();
                else
                    msg.Text = this.Name + " " + weapon.Description.Replace("{name}", "you") + "! (" + actualDamage.ToString() + ")";

                charToAttack.AddMessage(msg);
            }

            string soundName = "SwingHitSevere";

            int medium = CreatureToAttack.MaxHP - System.Convert.ToInt32(CreatureToAttack.MaxHP * .72);
            if (CreatureToAttack.HP > medium)
                soundName = "SwingHitModerate";

            int light = CreatureToAttack.MaxHP - System.Convert.ToInt32(CreatureToAttack.MaxHP * .28);
            if (CreatureToAttack.HP > light)
                soundName = "SwingHitLight";

            if (UseRange == true)
                soundName = soundName.Replace("Swing", "Arrow");

            if (skipHitSound == false)
            {
                foreach (Character character in CharactersInUpdateRange)
                    character.PlaySound(soundName, CreatureToAttack.MapX, CreatureToAttack.MapY);
            }

            //If we killed the creature, clear the hate list
            if (CreatureToAttack.HP < 1 && CreatureToAttack is Character)
            {
                Character character = (Character)CreatureToAttack;

                //Send Slain Message
                Message msgSlain = new Message();
                msgSlain.CreatureID = character.CreatureID;
                msgSlain.Text = "You have been SLAIN by " + this.Name + "!";
                msgSlain.Type = "slain";

                //Add message to update
                character.AddMessage(msgSlain);
            }
            
            return true;
        }

        public override string DamageBlock(int Accuracy, CreatureBase AttackingCreatureBase, out bool parry)
        {
            parry = false;

            string result = "";
            lock (this)
            {
                if (buffManager.IsStunned() == true)
                    return "";

                //Try dodge
                double dodge = Agility / 2;
                //if (Agility > Accuracy / 4.00)
                //    dodge = Accuracy / 4.00;

                if (GameHandler.random.Next(1, System.Convert.ToInt32(Math.Floor(dodge)) + Accuracy) <= dodge)
                    result = "Dodge";

                if (result == "")
                {
                    int totalDefense = SkillManager.AdjustForCombat(DefenseSkill, Defense, System.Convert.ToInt32(AgilityTotal / 1.50), 2);
                    int Range = Accuracy + totalDefense;
                    int Value = GameHandler.random.Next(1, Range + 1);

                    bool blocked = false;
                    if (Value > Accuracy)
                        blocked = true;

                    if (blocked == true)
                    {
                        if (RightHand == null && LeftHand == null)
                        {
                            if (HandBlockWeapon == "")
                                result = "hand";
                            else
                                result = HandBlockWeapon;
                        }
                        else
                        {
                            int weaponRange = 0;
                            int leftHandDef = 0;
                            if (LeftHand != null && LeftHand is Weapon)
                            {
                                Weapon left = (Weapon)LeftHand;
                                weaponRange = weaponRange + left.Defense;
                                leftHandDef = left.Defense;
                            }
                            if (RightHand != null && RightHand is Weapon)
                            {
                                Weapon right = (Weapon)RightHand;
                                weaponRange = weaponRange + right.Defense;
                            }
                            if (weaponRange == 0)
                                result = HandBlockWeapon;
                            else
                            {
                                int choosenWeapon = GameHandler.random.Next(1, weaponRange + 1);
                                if (choosenWeapon < leftHandDef)
                                    result = LeftHand.Name;
                                else
                                    result = RightHand.Name;
                            }
                        }
                    }
                }
                if (result != "")
                {
                    //Notify hate manager of attack
                    hateManager.UpdateList(AttackingCreatureBase, 0);

                    //We successfully blocked so if the attack is a character send them the message
                    if (AttackingCreatureBase is Character)
                    {
                        Character character = (Character)AttackingCreatureBase;

                        if (result != "Dodge")
                        {
                            Message blockMsg1 = new Message();
                            blockMsg1.Type = "damage";
                            blockMsg1.CreatureID = AttackingCreatureBase.CreatureID;
                            blockMsg1.Text = "You are blocked by " + this.Name + "\'s " + result + "!";
                            character.AddMessage(blockMsg1);
                        }
                        else
                        {
                            Message blockMsg1 = new Message();
                            blockMsg1.Type = "damage";
                            blockMsg1.CreatureID = character.CreatureID;
                            blockMsg1.Text = this.Name + " dodges!";
                            character.AddMessage(blockMsg1);
                        }
                    }
                }
            }
            return result;
        }
    }
}
